.model small
.data
	items db 16000 DUP (0)
	currentItem dw items
;=========================================
;	Display digits, letters & stuff
;=========================================
	DisplayKey0 db     "  #   # #  # #  # #   #  "
	DisplayKey1 db     "  #   ##    #    #    #  "
	DisplayKey2 db     " ##     #   #   #    ### "
	DisplayKey3 db     " ##     #  ##     #  ##  "
	DisplayKey4 db     " # #  # #  ###    #    # "
	DisplayKey5 db     " #### #    ###     # ### "
	DisplayKey6 db     "  ##  #    ###  #  #  ## "
	DisplayKey7 db     " ###    #    #    #    # "
	DisplayKey8 db     " ### #   # ### #   # ### "
	DisplayKey9 db     "  ##  #  #  ###    #  ## "
	
	DisplayKeyA db     "  #   # #  # #  ###  # # "
	DisplayKeyB db     " ###  #  # ###  #  # ### "
	DisplayKeyC db     "  ##  #  # #    #  #  ## "
	DisplayKeyD db     " ###  #  # #  # #  # ### "
	DisplayKeyE db     " ###  #    ###  #    ### "
	DisplayKeyF db     " ###  #    ###  #    #   "
	DisplayKeyG db     "  ##  #  # #    # ##  # #"
	DisplayKeyH db     " # #  # #  ###  # #  # # "
	DisplayKeyI db     " ###   #    #    #   ### "
	DisplayKeyJ db     "   #    #    #  # #   #  "
	DisplayKeyK db     " # #  # #  ##   # #  # # "
	DisplayKeyL db     " #    #    #    #    ### "
	DisplayKeyM db     "#   ### ### # ##   ##   #"
	DisplayKeyN db     " #  # ## # # ## #  # #  #"
	DisplayKeyO db     "  ##  #  # #  # #  #  ## "
	DisplayKeyP db     " ###  #  # ###  #    #   "
	DisplayKeyQ db	   "  ##  #  # #  # # #   # #"
	DisplayKeyR db     " ###  #  # ###  # #  #  #"
	DisplayKeyS db     "  ### #     ##     # ### "
	DisplayKeyT db     " ###   #    #    #    #  "
	DisplayKeyU db     " #  # #  # #  # #  #  ## "
	DisplayKeyV db     " # #  # #  # #  # #   #  "
	DisplayKeyW db     "#   ##   ## # ## # # # # "
	DisplayKeyX db     " # #  # #   #   # #  # # "
	DisplayKeyY db     " # #  # #   #    #    #  "
	DisplayKeyZ db     " ####   #   #   #    ####"
	DisplayKeySpace db "                         "
	DisplayKeyDash db  "            -            "
	DisplayKeyStar db  "\ | / \|/ --*-- /|\ / | \"
	DisplayWelcomeNote1 db " Projekat iz Mikroprocesorskih sistema:                                         "
	DisplayWelcomeNote2 db " Autori:                                              Tomic Aleksandar   07/387 "
	DisplayWelcomeNote3 db "                                                      Marko Milenkovic   07/002 "
	DisplayWelcomeNote4 db " Mentor:                                              Sasa Stojanovic           "
	DisplaySeparator 	db "--------------------------------------------------------------------------------"
;=================================================
; temp buffers
;=================================================
	StringOutputBuffer db '          $'
	StringWorkingBuffer db "                                        "
	StringInputBuffer db "                              "
	currentPrice dw 0
	entryCnt dw 0
	
;================================================
;	MATRIX DISPLAY MESSAGES
;================================================
	stringMatrixDisplay db '                $'
	
	stringMatrixDisplayProgramming db "programming     "
	stringMatrixDisplayFunc      db "func            "
	stringMatrixDisplayTotal 		db "sum             "
	stringMatrixDisplayWait 		db "init            "
	stringMatrixDisplayBill 		db "bill            "
	stringMatrixDisplayError			db "err             "
	
;================================================
; PRODUCT INFO
;================================================	
	product_name db "123456789ABC"
	unit_price dw 0
	qty dw 0
	currentBill dw 0
	total_traffic dw 0
	currentItemId dw 0
	previousItemId dw 0
	billStarted dw 0
	
;==============================
; TIMER
;==============================	
	CLOCK_HOURS db 0	
	CLOCK_MINUTES db 0
	CLOCK_SECONDS db 0
	showClock db 1
;=================================
; STATES
;=================================	
	STATE_CURRENT db 0
	STATE_PREVIOUS db 0
	STATE_WAIT equ 00h
	STATE_ADD_ITEMS equ 01h
	STATE_ENTER_NAMES equ 02h
	STATE_ENTER_PRICE equ 03h
	STATE_ENTER_TIME equ 04h
	STATE_READY equ 05h
	STATE_SEARCH_PRODUCT_ID equ 06h
	STATE_ENTER_QTY equ 07h
	STATE_BILL equ 08h
	STATE_FUNCTION equ 09h
	STATE_ERROR equ 0Ah
	STATE_BUSY equ 0Bh
	stanje_ispis_promet equ 0Ch
	
	
	msgConst0 db '0$'
	msgConstDash db '-$'
	
	old_timer_routine	dw 2 dup (0)
	ticks_in_timer_count db 0
;====================================================
; printer messages	
;====================================================
	msgPrinter00 			db "                    "
	msgPrinter01 			db "                    "
	msgPrinter02 			db "                    "
	msgPrinter03 			db "                    "
	msgPrinter04 			db "                    "
	msgPrinter05 			db "                    "
	msgPrinter06 			db "                    "
	msgPrinter07 			db "                    "
	msgPrinter08 			db "                    "
	msgPrinter09 			db "                    "
	msgPrinter10 			db "                    "
	msgPrinter11 			db "                    "
	msgPrinter12 			db "                    "
	msgPrinter13 			db "                    "
	msgPrinter14 			db "                    "
	msgPrinterWidth 		dw 20 
	msgPrinterEmpty 		db "                    "
	msgPrinterSeparator 	db "===================="
	msgPrinterTemp 			db "                    "
	
	msgTotal 				db "Total:"
	
	msgSerial00 db 30 dup (32)
	msgSerial01 db 30 dup (32)
	msgSerial02 db 30 dup (32)
	msgSerial03 db 30 dup (32)
	msgSerial04 db 30 dup (32)
	msgSerial05 db 30 dup (32)
	msgSerial06 db 30 dup (32)
	msgSerial07 db 30 dup (32)
	msgSerial08 db 30 dup (32)
	msgSerial09 db 30 dup (32)
	msgSerial10 db 30 dup (32)
	msgSerial11 db 30 dup (32)
	msgSerial12 db 30 dup (32)
	msgSerial13 db 30 dup (32)
	msgSerial14 db 30 dup (32)
	msgSerialWidth equ 30
	msgSerialEmpty 				db 		"                              "
	msgSerialConnect 			db 		" < Serial Connection Request  "
	msgSerialConnectOK 			db 		" > Serial Connection Ack      "
	msgSerialSet 				db 		" < Set Req		               "
	msgSerialSetOK 				db 		" > Set Ack                    "
	msgSerialDisconnect 		db 		" <-/- Request                 "
	msgSerialDisconnectOK 		db 		" -/-> Ack                     "
	msgSerialConnectToPC 		db 		" CR > PC [Connect]            "
	msgSerialConnectToPCOK 		db 		" CR < PC [Connect ACK]        "
	msgSerialDisconnectToPC 	db 		" CR -/-> PC [Disconnect]      "
	msgSerialDisconnectToPCOK 	db 		" CR <-/- PC [Disconnect ACK]  "
	
	msgSerialSend 				db 		' --> Send "            ",     '
	msgSerialSendOK				db 		' <-- Send OK                  '
	msgSerialTemp 				db 		"                              "
	
	
	charExit equ 1Bh ; ESC - izlazak iz simulatora
	
.stack 256h
.code

;=============================================================================
;TIMER_ROUTINE_INIT - menjanje prekidne rutine tajmera (ulaz 1Ch)
; stara prekidna rutina cuva se old_timer_routine
;		Input:  n/a
;		Output: n/a
;=============================================================================

TIMER_ROUTINE_INIT proc far
	push ax
	push es
	
	;ES = segment IVT
	mov ax, 0000h					
	mov es, ax
	;offset stare prekidne rutine
	mov ax, es:[1Ch*4]				
	mov word ptr old_timer_routine, ax
	;segment stare prekidne rutine
	mov ax, es:[1Ch*4 + 2]
	mov word ptr old_timer_routine+2, ax

	cli	;onemogucavaju se prekidi jer se snima u IVT
	mov word ptr es:[1Ch*4], offset new_timer_routine	;snimanje ofseta nove prekidne rutine u IVT
	mov word ptr es:[1Ch*4 + 2], seg new_timer_routine	;snimanje segmenta nove prekidne rutine u IVT
	sti	;ponovo su omoguceni prekidi

	pop es
	pop ax
	
	retf
TIMER_ROUTINE_INIT endp


;*************************************************************************
;TIMER_ROUTINE_RESTORE - vracanje adrese originalne prekidne rutine tajmera
;		Input:  n/a
;		Output: n/a
;*************************************************************************
TIMER_ROUTINE_RESTORE proc far
	push ax
	push es
	push ds
	
	;ES = segment IVT
	mov ax, 0000h
	mov es, ax
	cli		;onemogucavaju se prekidi dok se snima u IVT
	mov ax, word ptr old_timer_routine
	mov es:[1Ch*4], ax
	mov ax, word ptr old_timer_routine+2
	mov es:[1Ch*4+2], ax
	sti    ;omogucavanje prekida
	
	pop ds
	pop es
	pop ax

	retf
TIMER_ROUTINE_RESTORE endp

;********************************************************************************
; ProgramLoop - glavna petlja programa
;	Input: n/a
;	Output: n/a
;********************************************************************************
ProgramLoop PROC
lblReadKey:
	xor ax,ax
	call ReadKey
	
	cmp al, 46h ; F
	jz lblProgrammingModeFirst
	cmp al, 66h ; f
	jz lblProgrammingModeFirst
	jmp lblReadKey ; ceka se F ili f
	
lblProgrammingModeFirst:
	mov STATE_CURRENT, STATE_ADD_ITEMS
	call PrintDisplay
	;hand-shake
	mov si, offset msgSerialConnect
	call AddStringToSerial
	mov si, offset msgSerialConnectOK
	call AddStringToSerial
	
lblProgrammingMode:
	mov STATE_CURRENT, STATE_ADD_ITEMS 
	xor ax,ax
	call ReadKey
	
	; ukoliko je F ili f, prelazi se na unos vremena
	cmp al, 46h ; F
	jz lblEnterTimeJmp
	cmp al, 66h ; f
	jz lblEnterTimeJmp
	
	cmp al, 2Bh ; +
	jz lblUnosNaziva
	
	jmp lblProgrammingMode
	
;potrebno zbog offseta
lblEnterTimeJmp:
	jmp lblEnterTime
	
	
lblUnosNaziva:
	mov STATE_CURRENT, STATE_ENTER_NAMES
	mov di, 0
	mov bx, offset StringInputBuffer
	mov cx, 12
	call FlushString
	
	
lblNazivPetlja:
	cmp di, 12
	je lblGoToPrice
	xor ax, ax
	call ReadKey
	cmp al, 2Ah ; *
	je lblProcitanNaziv
	mov StringInputBuffer[di], al
	inc di
	jmp lblNazivPetlja
	
lblGoToPrice:
	xor ax,ax
	call ReadKey
	cmp al, 2Ah ; *
	jne lblGoToPrice
	
lblProcitanNaziv:
	mov ax, 0
	mov currentPrice, ax
	mov bx, 10
	
lblPrceLoop:
	xor ax, ax
	call ReadKey
	cmp al, 3Dh ; '='
	je lblProcitanaCena
	sub al, 30h ; -'0'
	xor ah,ah
	;ax = currentPrice * 10 + novi znak
	push ax
	mov ax, currentPrice 
	mul bx
	mov dx, ax
	pop ax
	add ax,dx
	mov currentPrice, ax
	jmp lblPrceLoop
	
lblProcitanaCena:
	;zapisati u evidenciju
	mov si, offset StringInputBuffer
	mov di, currentItem
	xor bx, bx
	mov cx,12
	call StringCopy
	
	add di, 12
	mov bx, currentPrice
	mov [di],bx
	add di,4
	mov currentItem, di
	;evidentirano i pomerena "glava"
	
	;slanje kroz serijski port
	mov si, offset msgSerialSet
	mov di, offset StringWorkingBuffer
	xor bx, bx
	mov cx, msgSerialWidth
	call StringCopy
	
	mov ax, entryCnt
	call WordToString
	
	mov si, offset StringOutputBuffer
	mov di, offset StringWorkingBuffer
	mov bx, 8 ; pomeraj u dest
	mov dx, 7 ; pomeraj u src
	mov cx, 3 ; duzina sifre
	call StringCopyExtended
	
	mov StringWorkingBuffer[11], ','
	mov StringWorkingBuffer[12], ' '
	mov StringWorkingBuffer[13], '"'
	
	mov si, offset StringInputBuffer
	mov di, offset StringWorkingBuffer
	mov bx, 14 ; pomeraj u dst
	xor dx, dx
	mov cx, 12
	call StringCopy
	
	mov StringWorkingBuffer[26], '"'
	mov StringWorkingBuffer[27], ','
	mov StringWorkingBuffer[28], ' '
	
	mov ax, currentPrice
	call WordToString
	
	mov si, offset StringOutputBuffer
	mov di, offset StringWorkingBuffer
	mov bx, 29 ; pomeraj u dest
	mov dx, 5 ; pomeraj u src
	mov cx, 5 ; duzina cene
	call StringCopyExtended
	
	; sad ubacimo u serijski red
	mov si, offset StringWorkingBuffer
	call AddStringToSerial
	; mora se povecati entryCnt
	inc entryCnt
	
	;potvrda
	mov si, offset msgSerialSetOK
	call AddStringToSerial
	;povratak da se ceka sledeci unos
	jmp lblProgrammingMode

lblEnterTime:
	mov STATE_CURRENT, STATE_ENTER_TIME
	xor ax,ax
	call ReadKey
	sub al, 30h ; -'0'
	mov bl,10
	mul bl
	mov CLOCK_HOURS, al ;desetica sata
	xor ax, ax
	call ReadKey
	sub al, 30h; -'0'
	add al, CLOCK_HOURS
	cmp al, 0
	jl lblFixClockHours
	cmp al, 24
	jle lblFinishClockHours
lblFixClockHours:
	mov al, 0
lblFinishClockHours:
	mov CLOCK_HOURS, al 
	;citanje minuta
	xor ax, ax
	call ReadKey
	sub al, 30h ; -'0'
	mov bl, 10
	mul bl
	mov CLOCK_MINUTES, al
	xor ax, ax
	call ReadKey
	sub al, 30h ;-'0'
	add al, CLOCK_MINUTES
	cmp al, 0
	jl lblFixClockMinutes
	cmp al, 60
	jle lblFinishClockMinutes
lblFixClockMinutes:
	mov al,0
lblFinishClockMinutes:
	mov CLOCK_MINUTES, al
	;citanje sekundi
	xor ax,ax
	call ReadKey
	sub al, 30h ;-'0'
	mov bl,10
	mul bl
	mov CLOCK_SECONDS, al
	xor ax, ax
	call ReadKey
	sub al, 30h ;-'0'
	add al, CLOCK_SECONDS
	cmp al, 0
	jl lblFixClockSeconds
	cmp al, 60
	jle lblFinishClockSeconds
lblFixClockSeconds:
	mov al, 0
lblFinishClockSeconds:
	mov CLOCK_SECONDS, al
	
	
	;sad se ceka F, radi prekida serijskog prenosa
lblWaitDisconnect:	
	xor ax,ax
	call ReadKey
	cmp al, 46h ; F
	jz lblGoToReady
	cmp al, 66h ; f
	jnz lblWaitDisconnect

lblGoToReady:
	mov STATE_CURRENT, STATE_READY
	call PrintDisplay
	
	xor ax, ax
	call ReadKey
	cmp al, 46h ; F
	jz lblFuntionSelect
	cmp al, 66h ; f
	jz lblFuntionSelect
	
	;provera da li je cifra
	cmp al, 30h ; '0'
	jl lblErrorLabel
	cmp al, 39h ; '9'
	jg lblErrorLabel
	; skacemo na obradu sifre
	
	jmp lblSearchById
	
	
lblErrorLabel:	
	call ErrorState
	jmp lblGoToReady
	
lblFuntionSelect:
	mov STATE_CURRENT, STATE_FUNCTION
	call PrintDisplay
	
	xor ax, ax
	call ReadKey
	cmp al, 30h ; '0'
	jz lblSlanjeSerijski
	cmp al, 31h ; '1'
	jz lblPrintSold
	cmp al, 32h ; '2'
	jz lblTraffic
	cmp al, 33h ; '3'
	jz lblTilt
	
	;korisnik moze i da odustane
	cmp al, 43h ; C
	jz lblCancelFunction
	cmp al, 63h ; c
	jz lblCancelFunction
	
	;ukoliko nije 0-3 ili C, greska
	call ErrorState
	jmp lblFuntionSelect
	
lblPrintSold:
	jmp lblPrintSold2
	
lblCancelFunction:
	jmp lblGoToReady
	
lblTraffic:
	mov STATE_CURRENT, stanje_ispis_promet
	call PrintDisplay
	;zadrzavanje neko vreme
	call Sleep
	
	jmp lblGoToReady
	
lblTilt:
	;beep
	mov ax, 0907h ; 
	xor bx,bx
	int 10h
	jmp lblGoToReady
	
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;	
lblSlanjeSerijski:
	mov STATE_CURRENT, STATE_BUSY
	call PrintDisplay
	
	;prvo moramo ispisati poruke za hand-shaking za konekciju
	mov si, offset msgSerialConnectToPC
	call AddStringToSerial
	mov si, offset msgSerialConnectToPCOK
	call AddStringToSerial
	
	; potrebno je pronaci artikle koji su prodati vise puta
	mov si, offset items
	mov di, offset items
	add di, 14 ; na kolicinu
	mov cx, entryCnt
	
lblSerijskoSlanjeLoop:
	push cx ; trebace registar u petlji, a mora se sacuvati za loop na kraju
	mov ax, [di] ; cita se qty
	cmp ax, 0
	jz lblSerijskoSlanjePredKraj
	
	xor bx, bx
	mov [di], bx ;upisuje se 0 u kolicinu artikla
	
	call WordToString ; qty
	
	mov ax, si
	mov dx, di ;backup
	
	mov si, offset msgSerialSend
	mov di, offset msgSerialTemp
	xor bx, bx
	mov cx, msgSerialWidth
	call StringCopy
	
	push dx
	mov si, offset StringOutputBuffer
	mov di, offset msgSerialTemp
	mov bx, 25 ; pomeraj u dst
	mov cx, 5
	mov dx, 5 ; pomeraj u src
	call StringCopyExtended
	pop dx
	
	mov si, ax ; ime proizvoda
	mov di, offset msgSerialTemp
	mov bx, 10
	mov cx, 12
	call StringCopy
	
	;pauza
	call Sleep
	
	;hand shaking
	mov si, offset msgSerialTemp
	call AddStringToSerial
	
	mov si, offset msgSerialSendOK
	call AddStringToSerial
	
	mov si, ax
	mov di, dx	
	
lblSerijskoSlanjePredKraj:
	add si, 16
	add di, 16 ;next
	
	pop cx
	loop lblSerijskoSlanjeLoop
	
	;sad se treba diskonektovati
	mov si, offset msgSerialDisconnectToPC
	call AddStringToSerial
	mov si, offset msgSerialDisconnectToPCOK
	call AddStringToSerial
	
	jmp lblGoToReady

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
lblPrintSold2:
	mov STATE_CURRENT, STATE_BUSY
	call PrintDisplay
	
	mov si, offset items
	mov di, offset items
	add di, 14 ;broj prodatih
	mov cx, entryCnt
	
lblStampanjeProdLoop:
	push cx ; trebace nam registar, pa da se sacuva za iteriranje
	
	mov ax, [di] ; citamo kolicinu
	
	cmp ax, 0
	jz lblStampanjePredKrajLoopa
	
	xor bx, bx
	mov [di], bx ; upisujemo 0
	
	call WordToString ;qty
	
	mov ax, si ;backup
	mov dx, di
	;qty s desne strane
	mov si, offset StringOutputBuffer
	mov di, offset msgPrinterTemp
	mov bx, 10 ; pomeraj u dest
	mov cx, 10
	call StringCopy
	
	;ime proizvoda s leve
	mov si, ax ; u ax se nalazi pomeraj evidencije
	mov di, offset msgPrinterTemp
	xor bx, bx
	mov cx, 12
	call StringCopy
	
	mov msgPrinterTemp[12], ':'
	
	;pauza
	call Sleep
	
	mov si, offset msgPrinterTemp
	call AddStringToBill
	
	;povratak iz backupa
	mov si, ax
	mov di, dx
		
lblStampanjePredKrajLoopa:
	add si, 16
	add di, 16 ;pomeranje na sledeci artikal
	
	pop cx ; bio je sacuvan na pocetku petlje
	loop lblStampanjeProdLoop
	
	; 3 prazna reda
	mov si, offset msgPrinterEmpty
	call AddStringToBill
	call AddStringToBill
	call AddStringToBill	
	
	jmp lblGoToReady
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	
lblPrelazakSpremanSifraRucka:
	jmp lblGoToReady

	
lblSearchById:
	sub al, 30h ; sad je broj
	xor ah,ah
	cmp ax, entryCnt
	jl lblSifraOpsegOKRanije
	call ErrorState
	cmp STATE_CURRENT, STATE_READY
	je lblPrelazakSpremanSifraRucka
	jmp lblPrelazakRacun
	
lblPrelazKolicinaRucka:
	jmp lblPrelazKolicina
	
lblSifraTarabaRucka:
	jmp lblSifraTaraba

lblSifraOpsegOKRanije:	
	mov previousItemId, 0
	mov currentItemId, ax
	mov qty, 1

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;	
lblSifraOpsegOK:
	;pronaci podatke o proizvodu
	mov STATE_CURRENT, STATE_SEARCH_PRODUCT_ID
	call SearchRecords
	call PrintDisplay
	
	; treba obaviti citanje karaktera i dalju akciju 
lblSifraPetlja:
	xor ax, ax
	call ReadKey
	;pre cifri proveriti ostalo
	cmp al, 43h ; C
	jz lblSifraOdustajanje
	cmp al, 63h ; c
	jz lblSifraOdustajanje
	cmp al, 2Bh ; +
	jz lblSifraPlus
	cmp al, 23h ; #
	jz lblSifraTarabaRucka
	cmp al, 2Ah ; *
	jz lblPrelazKolicinaRucka
	cmp al, 30h ; '0'
	jl lblSifraGreska
	cmp al, 39h ; '9'
	jg lblSifraGreska
	;cifra je
	
	xor ah, ah ; visi deo nije bitan
	sub al, 30h ; atoi
	mov cx, ax ; sacuvati cifru jedinicu
	mov ax, currentItemId 
	mov previousItemId, ax ;sacuvati staru u slucaju greske
	mov bx, 10 ; pomnoziti staru sifru sa 10 i dodati novu cifru
	mul bx
	add ax, cx
	mov currentItemId, ax
	
	cmp ax, entryCnt
	jl lblSifraOpsegOK
	call ErrorState
	call PrintDisplay
	jmp lblSifraPetlja

lblSifraGreska:
	call ErrorState
	call PrintDisplay
	jmp lblSifraPetlja
	
lblSifraOdustajanje:
	mov dx, billStarted
	cmp dx, 0
	je lblPrelazakSpremanSifOduRucka
	jmp lblPrelazakRacun
	
lblPrelazakSpremanSifOduRucka:
	jmp lblGoToReady
	
lblSifraPlus:
	mov ax, unit_price
	mul qty
	add currentBill, ax ;dodajemo cenu na vrednost racuna
	
	
	; da ocistimo radni string
	mov si, offset msgPrinterEmpty
	mov di, offset msgPrinterTemp
	xor bx, bx
	mov cx, msgPrinterWidth
	call StringCopy
	
	;izgled stavke:
	;ime proizvoda
	;(-)qty x jed. cena
	mov si, offset product_name
	mov di, offset msgPrinterTemp
	xor bx, bx
	mov cx, 12
	call StringCopy
	
	mov si, offset msgPrinterTemp
	call AddStringToBill
	
	; da ocistimo radni string
	mov si, offset msgPrinterEmpty
	mov di, offset msgPrinterTemp
	xor bx, bx
	mov cx, msgPrinterWidth
	call StringCopy
	
	mov ax, qty
	call WordToString
	mov si, offset StringOutputBuffer
	mov di, offset msgPrinterTemp
	mov bx, 1 ; prvo mesto je rezervisano za eventualni minus
	mov cx, 10 ;mada nece biti ovoliko
	call StringCopyLeft ; zanemaruju se blanko znaci, ne bi li bilo poravnato sa levom ivicom
	
	mov ax, unit_price
	call WordToString
	mov si, offset StringOutputBuffer
	mov di, offset msgPrinterTemp
	mov bx, 10
	mov cx, 10
	call StringCopy
	
	mov msgPrinterTemp[10], 'x'
	
	mov si, offset msgPrinterTemp
	call AddStringToBill
	
	mov si, currentItemId
	shl si, 4 ; * 16 (duzina jedne evidencije u B)
	add si, offset items
	add si, 14 ; pozicioniranje na do tad potrosene kolicine
	mov ax, [si]
	add ax, qty
	mov [si], ax ; upisivanje azurirane vrednosti
	
	mov currentItemId, 0
	jmp lblPrelazakRacun
	
lblSifraTaraba:
;izuzetno slicno kao i '+'
	mov ax, unit_price
	mul qty
	sub currentBill, ax ;ovde oduzimamo cenu na vrednost racuna
	
	
	; da ocistimo radni string
	mov si, offset msgPrinterEmpty
	mov di, offset msgPrinterTemp
	xor bx, bx
	mov cx, msgPrinterWidth
	call StringCopy
	
	;izgled stavke:
	;ime proizvoda
	;(-)qty x jed. cena
	mov si, offset product_name
	mov di, offset msgPrinterTemp
	xor bx, bx
	mov cx, 12
	call StringCopy
	
	mov si, offset msgPrinterTemp
	call AddStringToBill
	
	; da ocistimo radni string
	mov si, offset msgPrinterEmpty
	mov di, offset msgPrinterTemp
	xor bx, bx
	mov cx, msgPrinterWidth
	call StringCopy
	
	mov ax, qty
	call WordToString
	mov si, offset StringOutputBuffer
	mov di, offset msgPrinterTemp
	mov bx, 1 ; prvo mesto je rezervisano za eventualni minus
	mov cx, 10 ;mada nece biti ovoliko
	call StringCopyLeft ; zanemaruju se blanko znaci, ne bi li bilo poravnato sa levom ivicom
	
	mov ax, unit_price
	call WordToString
	mov si, offset StringOutputBuffer
	mov di, offset msgPrinterTemp
	mov bx, 10
	mov cx, 10
	call StringCopy
	
	mov msgPrinterTemp[10], 'x'
	mov msgPrinterTemp[0], '-' ;u ovom slucaju potreban je predznak
	
	mov si, offset msgPrinterTemp
	call AddStringToBill
	
	mov si, currentItemId
	shl si, 4 ; * 16 (duzina jedne evidencije u B)
	add si, offset items
	add si, 14 ; pozicioniranje na do tad potrosene kolicine
	mov ax, [si]
	sub ax, qty
	mov [si], ax ; upisivanje azurirane vrednosti
	
	mov currentItemId, 0
	jmp lblPrelazakRacun

lblPrelazKolicina:
	mov qty, 0
lblKolicinaPetlja:
	mov STATE_CURRENT, STATE_ENTER_QTY
	
	xor ax, ax
	call ReadKey
	cmp al, 43h ; C
	jz lblKolicinaBrisanje
	cmp al, 63h ; c
	jz lblKolicinaBrisanje
	cmp al, 2Bh ; +
	jz lblKolicinaPlus
	cmp al, 23h ; #
	jz lblKolicinaTaraba
	cmp al, 30h ; '0'
	jl lblKolicinaGreska
	cmp al, 39h ; '9'
	jg lblKolicinaGreska
	;cifra je
	
	;potrebno je pomeriti ulevo cifre i dodati novu
	xor ah, ah
	sub al, 30h ; - '0'
	push ax
	mov ax, qty
	mov bx, 10
	mul bx
	mov bx, ax
	pop ax
	add ax, bx
	mov qty, ax ; vracamo rezultat u kolicinu
	
	call PrintDisplay
	jmp lblKolicinaPetlja
	
lblKolicinaBrisanje:
	mov qty, 0
	call PrintDisplay
	jmp lblKolicinaPetlja

;postupak je isti, te se moze koristiti isti kod
lblKolicinaPlus:
	jmp lblSifraPlus

lblKolicinaTaraba:
	jmp lblSifraTaraba
	
lblKolicinaGreska:
	call ErrorState
	call PrintDisplay
	jmp lblKolicinaPetlja
	
lblPrelazakRacun:
;treba zapoceti racun ukoliko nije zapocet, i cekati = ili novu sifru
	mov billStarted, 1
	mov STATE_CURRENT, STATE_BILL
	call PrintDisplay
	xor ax, ax
	call ReadKey
	cmp al, 3Dh ; '='
	jz lblGotovRacun
	cmp al, 30h ; '0'
	jl lblRacunGreska
	cmp al, 39h ; '9'
	jg lblRacunGreska
	jmp lblSearchById
	
lblRacunGreska:
	call ErrorState
	jmp lblPrelazakRacun
	
lblGotovRacun:
	;odstampati kraj racuna, dodati totalni promet
	mov ax, currentBill
	add total_traffic, ax
	
	mov si, offset msgPrinterSeparator
	call AddStringToBill
	
	;ocistiti radni string
	mov bx, offset msgPrinterTemp
	mov cx, msgPrinterWidth
	call FlushString
	
	mov ax, currentBill
	call WordToString
	mov si, offset StringOutputBuffer
	mov di, offset msgPrinterTemp
	mov bx, 10 ; dst pomeraj
	mov cx, 10 ; duzina
	call StringCopy
	
	mov si, offset msgPrinterTemp
	call AddStringToBill
	
	; 3 reda razmaka
	mov si, offset msgPrinterEmpty
	call AddStringToBill
	call AddStringToBill
	call AddStringToBill
	
	;ponistavanje racuna
	mov currentBill, 0
	mov billStarted, 0
	;vratiti se u STATE_CURRENT spreman
	jmp lblGoToReady
	
	
	
	
	
	
	
ProgramLoop ENDP

;********************************************************************************
; ErrorState - funkcija koja ubacuje program u STATE_CURRENT greske i ceka C
;	Input: N/A
;   Output: N/A
;********************************************************************************
ErrorState PROC
	push ax
	;potrebno je sacuvati staro STATE_CURRENT, radi vracanja sistema na prethodno STATE_CURRENT
	mov al, STATE_CURRENT
	mov STATE_PREVIOUS, al
	mov STATE_CURRENT, STATE_ERROR
	;ispis greske
	call PrintDisplay
lblWaitForCKey:
	;cekanje da se pritisne C ili c
	xor ax, ax
	call ReadKey
	cmp al, 43h ; C
	jz lblCKeyHere
	cmp al, 63h ; c
	jnz lblWaitForCKey
lblCKeyHere:
	mov al, STATE_PREVIOUS
	mov STATE_CURRENT, al
	call PrintDisplay
	pop ax
	ret
	

ErrorState ENDP


;********************************************************************************
;	PrintDisplay - ispisuje sadrzaj sa stringMatrixDisplay na displayu
;		Input : 	
;		Output :	
;********************************************************************************
PrintDisplay PROC
	cli
	push ax
	push bx
	push dx
	push es
	push cx
	push si
	push di
	
	mov al, STATE_CURRENT
	cmp al, STATE_WAIT
	jz lblPrintCekam
	
	cmp al, STATE_ADD_ITEMS
	jz lblPrintProgramiranje
	cmp al, STATE_ENTER_NAMES
	jz lblPrintProgramiranje
	cmp al, STATE_ENTER_PRICE
	jz lblPrintProgramiranje
	cmp al, STATE_ENTER_TIME
	jz lblPrintProgramiranje
	cmp al, STATE_READY
	jz lblPrintSpreman
	cmp al, STATE_FUNCTION
	jz lblPrintFunkcija
	cmp al, STATE_BUSY
	jz lblPrintZauzet
	cmp al, STATE_ERROR
	jz lblPrintGreskaRucka
	cmp al, stanje_ispis_promet
	jz lblPrintPrometRucka
	cmp al, STATE_SEARCH_PRODUCT_ID
	jz lblPrintSifraRucka
	cmp al, STATE_BILL
	jz lblPrintRacunRucka
	cmp al, STATE_ENTER_QTY
	jz lblPrintKolicinaRucka
	
	jmp lblprintend

lblPrintGreskaRucka:
	jmp lblPrintGreska
	
lblPrintPrometRucka:
	jmp lblPrintPromet
	
lblPrintRacunRucka:
	jmp lblPrintRacun

lblPrintKolicinaRucka:
	jmp lblPrintKolicina
	
lblPrintSifraRucka:
	jmp lblPrintSifra
	
lblPrintCekam:
	;prvo ocistimo, pa unesemo
	mov bx, offset stringMatrixDisplay
	mov cx, 16
	call FlushString
	
	mov si, offset stringMatrixDisplayWait
	mov di, offset stringMatrixDisplay
	mov bx, 0
	mov cx, 16
	call StringCopy
	jmp lblRealPrint
	
lblPrintProgramiranje:
	mov bx, offset stringMatrixDisplay
	mov cx, 16
	call FlushString
	
	mov si, offset stringMatrixDisplayProgramming
	mov di, offset stringMatrixDisplay
	mov bx, 0
	mov cx, 16
	call StringCopy
	jmp lblRealPrint
	
lblPrintSpreman:
	;potrebno je ispisati vreme
	call SendTimeToDisplayString
	jmp lblRealPrint
	
lblPrintFunkcija:
;ispisacemo "funkcija"
	mov bx, offset stringMatrixDisplay
	mov cx, 16
	call FlushString
	
	mov si, offset stringMatrixDisplayFunc
	mov di, offset stringMatrixDisplay
	mov bx, 0
	mov cx, 16
	call StringCopy
	jmp lblRealPrint

lblPrintZauzet:	
;vreme i *
	call SendTimeToDisplayString
	mov byte ptr stringMatrixDisplay[15],'*'
	jmp lblRealPrint
	
lblPrintGreska:
;greska
	mov bx, offset stringMatrixDisplay
	mov cx, 16
	call FlushString
	
	mov si, offset stringMatrixDisplayError
	mov di, offset stringMatrixDisplay
	mov bx, 0
	mov cx, 16
	call StringCopy
	jmp lblRealPrint
	
lblPrintPromet:
;ispis dosadasnjeg prometa na displeju
	
	mov bx, offset stringMatrixDisplay
	mov cx, 16
	call FlushString
	
	mov ax, total_traffic
	call WordToString
	;rezultat je u StringOutputBuffer
	mov si, offset StringOutputBuffer
	mov di, offset stringMatrixDisplay
	mov bx, 3
	mov cx, 10
	call StringCopyLeft
	jmp lblRealPrint
	
lblPrintSifra:
;ispis naziva i cene artikla
	push ax
	mov ax, 1 ; qty
	; prvo cena krajnje desno
	mul word ptr unit_price
	call WordToString
	mov si, offset StringOutputBuffer
	mov di, offset stringMatrixDisplay
	mov bx, 6
	mov cx, 10
	call StringCopy
	; naziv na levoj strani
	mov si, offset product_name
	xor bx, bx
	mov cx, 12 ; duzina naziva, maksimalna
	call StringCopy
	pop ax
	jmp lblRealPrint
	
lblPrintRacun:
;ispis vrednosti trenutnog racuna
	mov bx, offset stringMatrixDisplay
	mov cx, 16
	call FlushString
	
	push ax
	mov ax, currentBill
	call WordToString
	mov si, offset StringOutputBuffer
	mov di, offset stringMatrixDisplay
	mov bx, 6
	mov cx, 10
	call StringCopy
	cmp ax, 0
	jge lblRacunPozitivan
	mov stringMatrixDisplay[0], '-'
lblRacunPozitivan:
	pop ax
	jmp lblRealPrint
	
lblPrintKolicina:
;potrebno je ispisati kolicinu levo, i vrednost desno
	mov bx, offset stringMatrixDisplay
	mov cx, 16
	call FlushString
	
	push ax
	mov ax, qty ; qty * jedinicna cena u desnom
	mul word ptr unit_price
	call WordToString
	mov si, offset StringOutputBuffer
	mov di, offset stringMatrixDisplay
	mov bx, 6 ;pomeraj u dst
	mov cx, 10 ; cnt
	call StringCopy
	
	mov ax, qty
	call WordToString
	mov si, offset StringOutputBuffer
	mov di, offset stringMatrixDisplay
	mov bx, 0
	mov cx, 10
	call StringCopyLeft ;pomereno u levo
	
	pop ax
	jmp lblRealPrint
	
	
;priprema za ispis	
lblRealPrint:
	lea di, stringMatrixDisplay
	mov cx, 16
	mov dx, 0
	xor ax, ax
	
;odredjivanje ascii karaktera	

;!!!!!!!!!!!!!!!!!!!!!
;zbog offseta pri skokovima mora da bude spageti kod
lblwritetextondisplay:
	mov al, [di]
	inc di
	
	cmp al, 32 ; ascii space
	jz lblwtdSpace
	;cifra
	cmp al, 48 ; ascii nula
	jz lblwtd0
	
	cmp al, 49 ; ascii 1
	jz lblwtd1
	
	cmp al, 50
	jz lblwtd2
	
	cmp al, 51
	jz lblwtd3
	
	cmp al, 52
	jz lblwtd4
	
	cmp al, 53
	jz lblwtd5
	
	cmp al, 54
	jz lblwtd6
	
	cmp al, 55
	jz lblwtd7
	
	cmp al, 56
	jz lblwtd8
	
	cmp al, 57  ;; broj 9
	jz lblwtd9
	
	jmp lblCompareLetters
	
		;kopiranje matrice karaktera za ispis
lblwtdSpace:
	lea si, DisplayKeySpace
	jmp lblwtdprint
	
lblwtd0:
	lea si, DisplayKey0
	jmp lblwtdprint
	
lblwtd1:
	lea si, DisplayKey1
	jmp lblwtdprint
	
lblwtd2:
	lea si, DisplayKey2
	jmp lblwtdprint
	
lblwtd3:
	lea si, DisplayKey3
	jmp lblwtdprint

lblwtd4:
	lea si, DisplayKey4
	jmp lblwtdprint

lblwtd5:
	lea si, DisplayKey5
	jmp lblwtdprint

lblwtd6:
	lea si, DisplayKey6
	jmp lblwtdprint

lblwtd7:
	lea si, DisplayKey7
	jmp lblwtdprint

lblwtd8:
	lea si, DisplayKey8
	jmp lblwtdprint

lblwtd9:
	lea si, DisplayKey9
	jmp lblwtdprint
	
	; sad slova: i mala i velika:
	
lblCompareLetters:
	cmp al, 45  ;; minus: -
	jz lblwtdDash
	
	cmp al, 42  ;; star
	jz lblwtdStar
	
	cmp al, 65
	jz lblwtdA
	cmp al, 97
	jz lblwtdA
	
	cmp al, 66
	jz lblwtdB
	cmp al, 98
	jz lblwtdB
	
	cmp al, 67
	jz lblwtdC
	cmp al, 99
	jz lblwtdC

	cmp al, 68
	jz lblwtdD
	cmp al, 100
	jz lblwtdD
	
	cmp al, 69
	jz lblwtdE
	cmp al, 101
	jz lblwtdE
	
	cmp al, 70
	jz lblwtdF
	cmp al, 102
	jz lblwtdF
	
	cmp al, 71
	jz lblwtdG
	cmp al, 103
	jz lblwtdG
	
	cmp al, 72
	jz lblwtdH
	cmp al, 104
	jz lblwtdH
	
	jmp lblCompareLettersI
	
lblwtdDash:
	lea si, DisplayKeyDash
	jmp lblwtdprint
	
lblwtdStar:
	lea si, DisplayKeyStar
	jmp lblwtdprint
	
lblwtdA:
	lea si, DisplayKeyA
	jmp lblwtdprint
	
lblwtdB:
	lea si, DisplayKeyB
	jmp lblwtdprint
	
lblwtdC:
	lea si, DisplayKeyC
	jmp lblwtdprint
	
lblwtdD:
	lea si, DisplayKeyD
	jmp lblwtdprint
	
lblwtdE:
	lea si, DisplayKeyE
	jmp lblwtdprint
	
lblwtdF:
	lea si, DisplayKeyF
	jmp lblwtdprint
	
lblwtdG:
	lea si, DisplayKeyG
	jmp lblwtdprint
	
lblwtdH:
	lea si, DisplayKeyH
	jmp lblwtdprint
	
lblwtdI:
	lea si, DisplayKeyI
	jmp lblwtdprint
	
lblwtdJ:
	lea si, DisplayKeyJ
	jmp lblwtdprint
	
	
lblCompareLettersI:	
	cmp al, 73
	jz lblwtdI
	cmp al, 105
	jz lblwtdI
	
	cmp al, 74
	jz lblwtdJ
	cmp al, 106
	jz lblwtdJ
	
	cmp al, 75
	jz lblwtdK
	cmp al, 107
	jz lblwtdK
	
	cmp al, 76
	jz lblwtdL
	cmp al, 108
	jz lblwtdL
	
	cmp al, 77
	jz lblwtdM
	cmp al, 109
	jz lblwtdM
	
	cmp al, 78
	jz lblwtdN
	cmp al, 110
	jz lblwtdN
	
	cmp al, 79
	jz lblwtdO
	cmp al, 111
	jz lblwtdO
	
	cmp al, 80
	jz lblwtdP
	cmp al, 112
	jz lblwtdP
	
	cmp al, 81
	jz lblwtdQ
	cmp al, 113
	jz lblwtdQ
	
	cmp al, 82
	jz lblwtdR
	cmp al, 114
	jz lblwtdR
	
	cmp al, 83
	jz lblwtdS
	cmp al, 115
	jz lblwtdS
	
	cmp al, 84
	jz lblwtdT
	cmp al, 116
	jz lblwtdT
	
	cmp al, 85
	jz lblwtdU
	cmp al, 117
	jz lblwtdU
	
	cmp al, 86
	jz lblwtdV
	cmp al, 118
	jz lblwtdV

	cmp al, 87
	jz lblwtdW
	cmp al, 119
	jz lblwtdW
	
	cmp al, 88
	jz lblwtdX
	cmp al, 120
	jz lblwtdX
	
	cmp al, 90
	jz lblwtdZ
	cmp al, 122
	jz lblwtdZ
	;kraj slova
	
	;ukoliko nije prepoznato, zanemaruje se
	dec cx
	jz lblprintend ;kraj ispisa
	jmp lblwritetextondisplay
	

	

	
lblwtdK:
	lea si, DisplayKeyK
	jmp lblwtdprint
	
lblwtdL:
	lea si, DisplayKeyL
	jmp lblwtdprint
	
lblwtdM:
	lea si, DisplayKeyM
	jmp lblwtdprint

lblwtdN:
	lea si, DisplayKeyN
	jmp lblwtdprint

lblwtdO:
	lea si, DisplayKeyO
	jmp lblwtdprint

lblwtdP:
	lea si, DisplayKeyP
	jmp lblwtdprint

lblwtdQ:
	lea si, DisplayKeyQ
	jmp lblwtdprint

lblwtdR:
	lea si, DisplayKeyR
	jmp lblwtdprint

lblwtdS:
	lea si, DisplayKeyS
	jmp lblwtdprint

lblwtdT:
	lea si, DisplayKeyT
	jmp lblwtdprint

lblwtdU:
	lea si, DisplayKeyU
	jmp lblwtdprint
	
lblwtdV:
	lea si, DisplayKeyV
	jmp lblwtdprint

lblwtdW:
	lea si, DisplayKeyW
	jmp lblwtdprint
	
lblwtdX:
	lea si, DisplayKeyX
	jmp lblwtdprint
	
lblwtdZ:
	lea si, DisplayKeyZ
	jmp lblwtdprint
	
;podaci su spremni, u registrima si i dx, treba pozvati proc za ispis
lblwtdprint:
	call PrintOneAsciiChar
	;pomeranje u matrici
	add dx, 10
	dec cx
	jz lblprintend ;; zavrsili smo sa ispisom, izlazimo iz procedure
	jmp lblwritetextondisplay  ;; vracamo se na pocetak
	
	
lblprintend:	
	pop di
	pop si
	pop cx
	pop es	
	pop dx
	pop bx
	pop ax
	sti
	ret
PrintDisplay ENDP

;********************************************************************************
;	ReadKey - ceka da se pritisne taster na tastaturi
;   softverski prekid na ulazu 16h, sa argumentom 10h kroz AH
;		Input :	nema
;		Output :	al - ASCII kod pritisnutog tastera
;					ah - scan code tastera
;********************************************************************************
ReadKey PROC
	push cx
	mov ah, 10h
	int 16h
	
	;izlazak u slucaju ESC
	cmp al, charExit;
	jnz lblRKSkip;
	call TIMER_ROUTINE_RESTORE
	call Exit;
	
lblRKSkip:	
	pop cx
	ret
ReadKey ENDP


;********************************************************************************
;	StringCopy - kopiranje jednog stringa na drugi
; **** probati izmeniti i odraditi sa instrukcijama za stringove ***********
;		Input : 	si - offset stringa iz koga se vrsi kopiranje
;					di - offset stringa u ukoji se vrsi kopiranje
;					bx - pozicija u destination stringu na koju se pocinje kopiranje
;					cx - broj karkatera koje treba iskopirati
;		Output :	nema
;********************************************************************************
StringCopy PROC
	cli
	push ax
	push bx
	push dx
	push es
	push cx
	push si
	push di
	
	add di, bx
	
	
stringCopyLoop:
	xor al, al
	mov al, [si]
	mov [di], al
	inc si
	inc di
	loop stringCopyLoop
	
	
	pop di
	pop si
	pop cx
	pop es	
	pop dx
	pop bx
	pop ax
	sti
	ret
StringCopy ENDP

;********************************************************************************
;	StringCopyLeft - kopiranje jednog stringa na drugi, zanemarivanje razmaka
; **** probati izmeniti i odraditi sa instrukcijama za stringove ***********
;		Input : 	si - offset stringa iz koga se vrsi kopiranje
;					di - offset stringa u ukoji se vrsi kopiranje
;					bx - pozicija u destination stringu na koju se pocinje kopiranje
;					cx - broj karkatera koje treba iskopirati
;		Output :	nema
;********************************************************************************
StringCopyLeft PROC
	cli
	push ax
	push bx
	push dx
	push es
	push cx
	push si
	push di
	
	add di, bx
	
	
stringCopyLeftLoop:
	xor al, al
	mov al, [si]
	cmp al, 20h ; space
	jz lblCopyLeftSkip
	mov [di], al
	inc di
lblCopyLeftSkip:
	inc si
	loop stringCopyLeftLoop
	
	
	pop di
	pop si
	pop cx
	pop es	
	pop dx
	pop bx
	pop ax
	sti
	ret
StringCopyLeft ENDP

;********************************************************************************
;	StringCopyExtended - kopiranje jednog stringa na drugi
;		Input : 	si - offset stringa iz koga se vrsi kopiranje
;					di - offset stringa u ukoji se vrsi kopiranje
;					bx - pozicija u destination stringu na koju se pocinje kopiranje
;					cx - broj karkatera koje treba iskopirati
;					dx - pozicija u source stringu odakle se pocinje kopiranje
;		Output :	nema
;********************************************************************************
StringCopyExtended PROC
	cli
	push ax
	push bx
	push dx
	push es
	push cx
	push si
	push di
	
	add di, bx
	
	; samo je ovo novo:
	add si, dx
	
stringCopyExtLoop:
	xor al, al
	mov al, [si]
	mov [di], al
	inc si
	inc di
	loop stringCopyExtLoop
	
	
	pop di
	pop si
	pop cx
	pop es	
	pop dx
	pop bx
	pop ax
	sti
	ret
StringCopyExtended ENDP

;*****************************************************************
;	FlushString - prazni sadrzaj stringa
;	Postavlja sve karaktere na znak space osim poslednjeg koji je $
;		Input:	bx - offset stringa koga treba isprazniti
;				cx - duzina stringa
;		Output:	nema
;*****************************************************************
FlushString PROC
	push bx
	push cx
	push dx
	push si
	
	mov dl, 20h  ; ascii space
	xor si, si
	moreChars:
		mov [bx][si], dl
		inc si
		loop moreChars
		
	pop si
	pop dx
	pop cx
	pop bx
	ret
FlushString ENDP


;***************************************************************************
;	 ByteToString - konvertuje bajt u string
;		Input :	al - bajt koji se konvertuje u string
;		Output:	StringOutputBuffer - niz karaktera koji predstavlja bajt
;***************************************************************************
ByteToString PROC	
	push cx
	push di
	push bx
	push ax			; u ah div instrukcija smesta rezultat pa i ovaj registar mora da se sacuva
	
	mov bx, offset StringOutputBuffer
	mov cx, 10
	call FlushString
	
	mov cx, 0003h	; u bajtu mogu da postoje maksimalno tri cifre
	mov di, 09h		; indeks niza OutputStringBuffer; niz se popunjava od poslednjeg elementa
	xor bx, bx
	mov bl, 0Ah		; delilac je 10 decimalno ili 0A hex

	moreByte :	
			div bl
			add ah, 30h ; 30h je ASCII za 0
			mov StringOutputBuffer[di], ah
			xor ah, ah
			dec di
			cmp al, 0h
			jnz moreByte
	
	pop ax
	pop bx
	pop di
	pop cx
	
	ret	
ByteToString ENDP

;***************************************************************************
;	 WordToString - konvertuje bajt u string
;		Input :	ax - word koji se konvertuje u string
;		Output:	StringOutputBuffer - niz karaktera koji predstavlja word
;***************************************************************************
WordToString PROC	
	push dx			; u registar dx se smesta ostatak od deljenja
	push cx
	push di
	push bx
	push ax
	
	mov bx, offset StringOutputBuffer
	mov cx, 10
	call FlushString
	
	mov cx, 0005h	; u wordu mogu da postoje maksimalno pet cifre
	mov di, 09h		; indeks niza OutputStringBuffer; niz se popunjava od poslednjeg elementa
	mov bx, 0Ah		; delilac je 10 decimalno ili 0A hex

	moreWord1:	
			xor dx, dx
			div bx
			add dl, 30h
			mov StringOutputBuffer[di], dl
			dec di
			cmp ax, 0h
			jnz moreWord1
	
	pop ax
	pop bx
	pop di
	pop cx
	pop dx
	
	ret	
WordToString ENDP




;**************************************************************************
; Kod nove prekidne rutine za tajmer (tajmer otkucava na 55ms)
; 18*55ms = 990ms ~ 1s
; broj otkucaja se pamti u globalnoj promenljivoj ticks_in_timer_count
;	Input - n/a
;	Output - n/a
;**************************************************************************

new_timer_routine proc far
	push ax
	push ds
	push es
	push di
	
	mov ax, _DATA   ;data segment
	mov ds, ax

	
	mov al, ticks_in_timer_count
	inc al
	mov ticks_in_timer_count, al
	cmp al, 18
	jnz lblEndTimer  ; ako nije izbrojano 18 tickova, skacemo na kraj procedure
	xor al, al  ; al = 0
	mov ticks_in_timer_count, al  ; ticks_in_timer_rout = 0
	
	
	call UpdateClock  ; azuriramo celobrojne vrednosti za vreme
	
	;osvezicemo ekran samo kad treba
	mov al, STATE_CURRENT
	cmp al, STATE_READY
	jz lblTimerPrint
	cmp al, STATE_BUSY
	jnz lblEndTimer
lblTimerPrint:
	call PrintDisplay
	

lblEndTimer:
	
	pop di
	pop es
	pop ds
	pop ax

	iret
new_timer_routine endp

;****************************************************************
; Azuriranje sata
; 	Input - n/a
;	Output - n/a
;****************************************************************

UpdateClock PROC NEAR	

	INC CLOCK_SECONDS
	CMP CLOCK_SECONDS, 60
	JNE	UpdateClock_end
	
	mov CLOCK_SECONDS, 0
	INC CLOCK_MINUTES
	CMP CLOCK_MINUTES, 60
	JNE UpdateClock_end
	
	MOV CLOCK_MINUTES, 0
	INC CLOCK_HOURS
	CMP CLOCK_HOURS, 24
	JNE UpdateClock_end
	
	MOV CLOCK_HOURS, 0
	
UpdateClock_end:	

  RET
UpdateClock ENDP


;********************************************************************************
;	SendTimeToDisplayString - upisivanje vremena u stringMatrixDisplay
;		Input : 	nema
;		Output :	nema
;********************************************************************************
SendTimeToDisplayString PROC
	cli
	push ax
	push bx
	push dx
	push es
	push cx
	push si
	push di
	
	mov al, showClock
	cmp al, 1
	jnz finishSendTimeToDspForw   ; ako ne treba da ispisemo vreme na displayu, izlazimo is procedure
	jmp lblTreabaDaMenjamo
	
finishSendTimeToDspForw:	jmp finishSendTimeToDsp
	
lblTreabaDaMenjamo:
	; flush output string
	xor bx, bx
	mov bx, offset StringOutputBuffer
	mov cx, 10
	call FlushString
	
	; flush display string
	mov bx, offset stringMatrixDisplay
	mov cx, 17  
	call FlushString
	
	;;;===================
	; glavna obrada procedure
	xor ax, ax
	xor bx, bx
	; prvo sate
	mov bl, CLOCK_HOURS
	cmp bl, 9
	jg dvocifreniSati
	
	; ovde jednocifreni
	; prvo cemo da upisemo jednu nulu
	mov si, offset msgConst0
	mov di, offset stringMatrixDisplay
	mov bx, 3
	mov cx, 1
	call StringCopy ; upisana nula
	; ne treba, upisujemo posle u bx; ovo ne treba: inc bx ; upisali smo jednu cifru, pomeramo pokazivac da bi odavde upisali narednu cifru
	
	mov al, CLOCK_HOURS  ; ByteToString trazi u al ono sto treba da konvertuje
	call ByteToString  
	mov si, offset StringOutputBuffer
	mov di, offset stringMatrixDisplay
	mov bx, 4
	mov cx, 1
	mov dx, 9  ; poslednji karakter iz StringOutputBuffer
	call StringCopyExtended
	
	jmp lblMinuti
	
dvocifreniSati:
	mov al, CLOCK_HOURS  ; ByteToString trazi u al ono sto treba da konvertuje
	call ByteToString  
	mov si, offset StringOutputBuffer
	mov di, offset stringMatrixDisplay
	mov bx, 3
	mov cx, 2
	mov dx, 8  ; pretposlednji karakter iz StringOutputBuffer
	call StringCopyExtended

lblMinuti:

	
	;; sad idu minuti
	mov bl, CLOCK_MINUTES
	cmp bl, 9
	jg dvocifreniMinuti
	
	; ovde jednocifreni
	; prvo cemo da upisemo jednu nulu
	mov si, offset msgConst0
	mov di, offset stringMatrixDisplay
	mov bx, 6
	mov cx, 1
	call StringCopy ; upisana nula
	
	
	mov al, CLOCK_MINUTES  ; ByteToString trazi u al ono sto treba da konvertuje
	call ByteToString  
	mov si, offset StringOutputBuffer
	mov di, offset stringMatrixDisplay
	mov bx, 7
	mov cx, 1
	mov dx, 9  ; poslednji karakter iz StringOutputBuffer
	call StringCopyExtended
	
	jmp lblSekunde
	
dvocifreniMinuti:
	mov al, CLOCK_MINUTES  ; ByteToString trazi u al ono sto treba da konvertuje
	call ByteToString  
	mov si, offset StringOutputBuffer
	mov di, offset stringMatrixDisplay
	mov bx, 6
	mov cx, 2
	mov dx, 8  ; pretposlednji karakter iz StringOutputBuffer
	call StringCopyExtended
	
	
	
	
lblSekunde:

	
	;; sad idu sekunde
	mov bl, CLOCK_SECONDS
	cmp bl, 9
	jg dvocifreneSekunde
	
	; ovde jednocifreni
	; prvo cemo da upisemo jednu nulu
	mov si, offset msgConst0
	mov di, offset stringMatrixDisplay
	mov bx, 9
	mov cx, 1
	call StringCopy ; upisana nula
	
	
	mov al, CLOCK_SECONDS  ; ByteToString trazi u al ono sto treba da konvertuje
	call ByteToString  
	mov si, offset StringOutputBuffer
	mov di, offset stringMatrixDisplay
	mov bx, 10
	mov cx, 1
	mov dx, 9  ; poslednji karakter iz StringOutputBuffer
	call StringCopyExtended
	
	jmp finishSendTimeToDsp
	
dvocifreneSekunde:
	mov al, CLOCK_SECONDS  ; ByteToString trazi u al ono sto treba da konvertuje
	call ByteToString  
	mov si, offset StringOutputBuffer
	mov di, offset stringMatrixDisplay
	mov bx, 9
	mov cx, 2
	mov dx, 8  ; pretposlednji karakter iz StringOutputBuffer
	call StringCopyExtended

finishSendTimeToDsp:	
	pop di
	pop si
	pop cx
	pop es	
	pop dx
	pop bx
	pop ax
	sti
	ret
SendTimeToDisplayString ENDP

;********************************************************************************
;	PrintOneAsciiChar - ispisivanje jednog karaktera na displayu
;		Input : 	dx - pocetna tacka matrice odakle se pocinje ispisivanje (pomnoziti sa 2 zbog data/pref)
;					si - offset podmatrice koju zelimo da ispisemo
;		Output :	nema
;********************************************************************************
PrintOneAsciiChar PROC
	cli
	push ax
	push bx
	push dx
	push es
	push cx
	push si
	push di
	
	
	;; -- upisivanje u es pocetne adrese video memorije --
	push ax
	mov ax, 0B800h
	mov es, ax
	pop ax
	
	xor bx, bx  ;; resetujemo bx -> sluzice nam za x * 80
spoljas:
	mov ax, 160   ;; 80 x 2 (podatak + prefs)
	mul bl
	add ax, dx  ;; ax = pocetak + 80*b  (b je redni broj vrste)
	
	mov di, ax;
	mov cx, 5 ; bice iterator, toliko kolona imamo (5x5 matrica)
	
	; print color
	; highest nibble background
	; lowest nibble foreground
	mov ah, 2Eh
	
unutras:
	mov al, [si]
	mov es:[di], ax
	inc di
	inc di
	inc si
	loop unutras
	
	; -- treba da sredimo i spoljasnju petlju
	inc bx
	cmp bx, 5
	jne spoljas
	
	
	pop di
	pop si
	pop cx
	pop es	
	pop dx
	pop bx
	pop ax
	sti
	ret
PrintOneAsciiChar ENDP

;********************************************************************************
;	AddStringToSerial - dodavanje novog stringa na serijski (i izbacivanje poslednjeg - FIFO)
;		Input : 	si - offset stringa koga zelimo da dodamo
;		Output :	nema
;********************************************************************************
AddStringToSerial PROC
	cli
	push ax
	push bx
	push dx
	push es
	push cx
	push si
	push di
	
	push si ; kasnije cemo da ga skinemo i iskoristimo

	mov ax, _DATA
	mov ds, ax
	
	
	xor cx, cx
	xor bx, bx
	mov cl, msgSerialWidth
	
	mov si, offset msgSerial13
	mov di, offset msgSerial14
	call StringCopy
	
	mov si, offset msgSerial12
	mov di, offset msgSerial13
	call StringCopy
	
	mov si, offset msgSerial11
	mov di, offset msgSerial12
	call StringCopy
	
	mov si, offset msgSerial10
	mov di, offset msgSerial11
	call StringCopy
	
	mov si, offset msgSerial09
	mov di, offset msgSerial10
	call StringCopy
	
	mov si, offset msgSerial08
	mov di, offset msgSerial09
	call StringCopy
	
	mov si, offset msgSerial07
	mov di, offset msgSerial08
	call StringCopy
	
	mov si, offset msgSerial06
	mov di, offset msgSerial07
	call StringCopy
	
	mov si, offset msgSerial05
	mov di, offset msgSerial06
	call StringCopy
	
	mov si, offset msgSerial04
	mov di, offset msgSerial05
	call StringCopy
	
	mov si, offset msgSerial03
	mov di, offset msgSerial04
	call StringCopy
	
	mov si, offset msgSerial02
	mov di, offset msgSerial03
	call StringCopy
	
	mov si, offset msgSerial01
	mov di, offset msgSerial02
	call StringCopy
	
	mov si, offset msgSerial00
	mov di, offset msgSerial01
	call StringCopy
	
	pop si  ;  ovde je offset stringa koji treba da dodamo
	mov di, offset msgSerial00
	call StringCopy
	
	
	; na kraju ispisemo nove stringove
	call PrintSerialStrings
	
	pop di
	pop si
	pop cx
	pop es	
	pop dx
	pop bx
	pop ax
	sti
	ret
AddStringToSerial ENDP

;********************************************************************************
;	PrintSerialStrings - ispisivanje stringova iz komunikacije sa racunarom preko serijskog porta
;		Input : 	nema
;		Output :	nema
;********************************************************************************
PrintSerialStrings PROC
	cli
	push ax
	push bx
	push dx
	push es
	push cx
	push si
	push di
	
	xor cx, cx
	
	mov dx, 1602 ;  10. red, uz levu ivicu
	mov ah, 0Eh ; bela
	mov cl, msgSerialWidth
	mov si, offset msgSerial00
	call PrintTextOnConsole
	
	add dx, 160
	mov si, offset msgSerial01
	call PrintTextOnConsole
	
	add dx, 160
	mov si, offset msgSerial02
	call PrintTextOnConsole
	
	add dx, 160
	mov si, offset msgSerial03
	call PrintTextOnConsole
	
	add dx, 160
	mov si, offset msgSerial04
	call PrintTextOnConsole
	
	add dx, 160
	mov si, offset msgSerial05
	call PrintTextOnConsole
	
	add dx, 160
	mov si, offset msgSerial06
	call PrintTextOnConsole
	
	add dx, 160
	mov si, offset msgSerial07
	call PrintTextOnConsole
	
	add dx, 160
	mov si, offset msgSerial08
	call PrintTextOnConsole
	
	add dx, 160
	mov si, offset msgSerial09
	call PrintTextOnConsole
	
	add dx, 160
	mov si, offset msgSerial10
	call PrintTextOnConsole
	
	add dx, 160
	mov si, offset msgSerial11
	call PrintTextOnConsole
	
	add dx, 160
	mov si, offset msgSerial12
	call PrintTextOnConsole
	
	add dx, 160
	mov si, offset msgSerial13
	call PrintTextOnConsole
	
	add dx, 160
	mov si, offset msgSerial14
	call PrintTextOnConsole
	
	
	pop di
	pop si
	pop cx
	pop es	
	pop dx
	pop bx
	pop ax
	sti
	ret
PrintSerialStrings ENDP

;********************************************************************************
;	AddStringToBill - dodavanje novog stringa na racun (i izbacivanje poslednjeg - FIFO)
;		Input : 	si - offset stringa koga zelimo da dodamo
;		Output :	nema
;********************************************************************************
AddStringToBill PROC
	cli
	push ax
	push bx
	push dx
	push es
	push cx
	push si
	push di
	
	push si ; kasnije cemo da ga skinemo i iskoristimo

	mov ax, _DATA
	mov ds, ax
	
	
	xor cx, cx
	xor bx, bx
	mov cx, msgPrinterWidth
	
	;shiftujemo
	mov si, offset msgPrinter13
	mov di, offset msgPrinter14
	call StringCopy
	
	mov si, offset msgPrinter12
	mov di, offset msgPrinter13
	call StringCopy
	
	mov si, offset msgPrinter11
	mov di, offset msgPrinter12
	call StringCopy
	
	mov si, offset msgPrinter10
	mov di, offset msgPrinter11
	call StringCopy
	
	mov si, offset msgPrinter09
	mov di, offset msgPrinter10
	call StringCopy
	
	mov si, offset msgPrinter08
	mov di, offset msgPrinter09
	call StringCopy
	
	mov si, offset msgPrinter07
	mov di, offset msgPrinter08
	call StringCopy
	
	mov si, offset msgPrinter06
	mov di, offset msgPrinter07
	call StringCopy
	
	mov si, offset msgPrinter05
	mov di, offset msgPrinter06
	call StringCopy
	
	mov si, offset msgPrinter04
	mov di, offset msgPrinter05
	call StringCopy
	
	mov si, offset msgPrinter03
	mov di, offset msgPrinter04
	call StringCopy
	
	mov si, offset msgPrinter02
	mov di, offset msgPrinter03
	call StringCopy
	
	mov si, offset msgPrinter01
	mov di, offset msgPrinter02
	call StringCopy
	
	mov si, offset msgPrinter00
	mov di, offset msgPrinter01
	call StringCopy
	
	pop si  ;  ovde je offset stringa koji treba da dodamo
	mov di, offset msgPrinter00
	call StringCopy
	
	
	; na kraju ispisemo nove stringove
	call PrintBillStrings
	
	pop di
	pop si
	pop cx
	pop es	
	pop dx
	pop bx
	pop ax
	sti
	ret
AddStringToBill ENDP

;********************************************************************************
;	PrintBillStrings - ispisivanje stringova sa racuna
;		Input : 	nema
;		Output :	nema
;********************************************************************************
PrintBillStrings PROC
	cli
	push ax
	push bx
	push dx
	push es
	push cx
	push si
	push di
	

	xor cx, cx
	
	mov dx, 1718  ;  10. red, uz desnu ivicu
	mov ah, 0Eh ; bela boja
	mov cx, msgPrinterWidth
	mov si, offset msgPrinter14
	call PrintTextOnConsole
	
	add dx, 160
	mov si, offset msgPrinter13
	call PrintTextOnConsole
	
	add dx, 160
	mov si, offset msgPrinter12
	call PrintTextOnConsole
	
	add dx, 160
	mov si, offset msgPrinter11
	call PrintTextOnConsole
	
	add dx, 160
	mov si, offset msgPrinter10
	call PrintTextOnConsole
	
	add dx, 160
	mov si, offset msgPrinter09
	call PrintTextOnConsole
	
	add dx, 160
	mov si, offset msgPrinter08
	call PrintTextOnConsole
	
	add dx, 160
	mov si, offset msgPrinter07
	call PrintTextOnConsole
	
	add dx, 160
	mov si, offset msgPrinter06
	call PrintTextOnConsole
	
	add dx, 160
	mov si, offset msgPrinter05
	call PrintTextOnConsole
	
	add dx, 160
	mov si, offset msgPrinter04
	call PrintTextOnConsole
	
	add dx, 160
	mov si, offset msgPrinter03
	call PrintTextOnConsole
	
	add dx, 160
	mov si, offset msgPrinter02
	call PrintTextOnConsole
	
	add dx, 160
	mov si, offset msgPrinter01
	call PrintTextOnConsole
	
	add dx, 160
	mov si, offset msgPrinter00
	call PrintTextOnConsole
	
	
	pop di
	pop si
	pop cx
	pop es	
	pop dx
	pop bx
	pop ax
	sti
	ret
PrintBillStrings ENDP

;********************************************************************************
;	SearchRecords - pretrazuje iteme za da trazeni id iz ax
;		Input : 	ax - id item-a
;		Output :	nema (globalne promenljive - stringovi i sl.)
;********************************************************************************
SearchRecords PROC
	cli
	push ax
	push bx
	push dx
	push es
	push cx
	push si
	push di
	
	shl ax, 4 ; mnozenje sifre zapamcene u al sa 16
	add ax, offset items
	; sad cemo da iskopiramo iz evidnecije potrebne stvari
	mov si, ax  ; tu je offset evidencije
	mov di, offset product_name
	xor bx, bx
	mov cx, 12
	call StringCopy
	
	add si, 12
	mov dx, [si]
	mov unit_price, dx

	pop di
	pop si
	pop cx
	pop es	
	pop dx
	pop bx
	pop ax
	sti
	ret
SearchRecords ENDP

;********************************************************************************
;	Sleep - radi busy wait 1 (ili 3) sekunde
;		Input : 	nema
;		Output :	nema
;********************************************************************************
Sleep PROC
	push ax
	push bx
	push dx
	push es
	push cx
	push si
	push di
	
	xor bx, bx
	xor ax, ax
	
	mov bl, CLOCK_SECONDS
	add bl, 3
	
	; if (bl > 59) { bl = 2; }
	cmp bl, 59
	jl lblSleepIfNeeded  ; skip next instruction
	mov bl, 2
	
lblSleepIfNeeded:
	mov al, CLOCK_SECONDS
	cmp al, bl
	jnz lblSleepIfNeeded


lblWWKraj:	
	pop di
	pop si
	pop cx
	pop es	
	pop dx
	pop bx
	pop ax
	ret
Sleep ENDP

;********************************************************************************
;	PrintTextOnConsole - ispisivanje stringa u display matrici (80x25)
;		Input : 	dx - pocetna tacka matrice odakle se pocinje ispisivanje (pomnoziti sa 2 zbog data/pref)
;					ah - boja
;					si - offset stringa koji zelimo da ispisemo
;					cx - duzina stringa
;		Output :	nema
;********************************************************************************
PrintTextOnConsole PROC
	cli
	push ax
	push bx
	push dx
	push es
	push cx
	push si
	push di
	
	
	;; -- upisivanje u es pocetne adrese video memorije --
	push ax
	mov ax, 0B800h
	mov es, ax
	pop ax
	
	
	mov di, dx
	
hasNext:
	mov al, [si]
	mov es:[di], ax ;u AH je boja, u AL vrednost
	inc di
	inc di
	inc si
	loop hasNext	
	
	
	pop di
	pop si
	pop cx
	pop es	
	pop dx
	pop bx
	pop ax
	sti
	ret
PrintTextOnConsole ENDP

;****************************************
;	DisableCursorBlinking - iskljucuje blinkovanje kursora (u gornjem levom uglu)
;****************************************
DisableCursorBlinking PROC
	push ax
	push cx
	
	mov ah, 01h
	mov cx, 2000h
	int 10h
	
	pop cx
	pop ax
	ret
DisableCursorBlinking ENDP

;****************************************
;	DrawScreen - procedura koja iscrtava ceo ekran
;	Input - n/a
;	Output - n/a
;****************************************
DrawScreen PROC
	push ax
	push cx
	
	call PrintDisplay
	
	
	call PrintBillStrings
	call PrintSerialStrings
	
	pop cx
	pop ax
	ret
DrawScreen ENDP

;********************************************************************************
;	Exit - izlazak iz programa i povratak u DOS
;		Input : 	nema
;		Output :	nema
;********************************************************************************
Exit PROC
	MOV AX, 4C00h
	int 21h
Exit ENDP

;===============================
; Separator
;===============================
ShowWelcomeNote PROC
	cli
	push ax
	push bx
	push cx
	push dx
	push es
	push si
	push di
	

	xor cx, cx
	
	mov dx, 800  
	mov ah, 2Eh 
	mov cx, 80
	mov si, offset DisplaySeparator
	call PrintTextOnConsole
	
	mov dx, 960  
	mov ah, 2Eh 
	mov cx, 80
	mov si, offset DisplayWelcomeNote1
	call PrintTextOnConsole
	
	mov dx, 1120  
	mov ah, 2Eh 
	mov cx, 80
	mov si, offset DisplayWelcomeNote2
	call PrintTextOnConsole
	
	mov dx, 1280  
	mov ah, 2Eh 
	mov cx, 80
	mov si, offset DisplayWelcomeNote3
	call PrintTextOnConsole
	
	mov dx, 1440  
	mov ah, 2Eh 
	mov cx, 80
	mov si, offset DisplayWelcomeNote4
	call PrintTextOnConsole
	
	pop di
	pop si
	pop es	
	pop dx
	pop cx
	pop bx
	pop ax
	sti
	ret
ShowWelcomeNote ENDP

;************************************************************
;	glavni program
;************************************************************
Main:
	mov ax, _DATA
	mov ds, ax

	mov ax, 3h
	int 10h
	
	
	
	call TIMER_ROUTINE_INIT
	call DrawScreen
	call DisableCursorBlinking
	call ShowWelcomeNote
	

	call ProgramLoop
	call TIMER_ROUTINE_RESTORE
	call Exit
end Main